package com.hm.service.framework.crypto.CBC;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * hm
 * AES加密模式
 * 增加了偏移量参数
 */
public class AES_CBC {

    private static final Logger logger = LoggerFactory.getLogger(AES_CBC.class);

    //定义加密算法
    private static final String Algorithm = "AES/CBC/PKCS5Padding";

    /**
     * @param secretKey   secretKey
     * @param ivParameter ivParameter
     * @param content     content
     * @return String
     */
    public static String encrypt(String secretKey, String ivParameter, String content) {
        try {
            //检查非空
            if (secretKey == null || secretKey.isEmpty()) {
                logger.error("secretKey为空");
                return "secretKey为空";
            }
            //检查长度
            if (secretKey.length() != 32) {
                logger.error("secretKey长度不等于32");
                return "secretKey长度不等于32";
            }
            //正则表达式标识匹配字符串中的非字母和非数字的的字符，如果字符中含有特殊字符，则会匹配成功
            Pattern pattern = Pattern.compile("[^A-Za-z0-9]");
            Matcher matcher = pattern.matcher(secretKey);
            if (matcher.find()) {
                //说明有特殊字符
                logger.error("secretKey含有特殊字符");
                return "secretKey含有特殊字符";
            }
            //***************检查非空
            if (ivParameter == null || ivParameter.isEmpty()) {
                logger.error("ivParameter为空");
                return "ivParameter为空";
            }
            //检查长度
            if (ivParameter.length() != 16) {
                logger.error("ivParameter长度不等于16");
                return "ivParameter长度不等于16";
            }
            //正则表达式标识匹配字符串中的非字母和非数字的的字符，如果字符中含有特殊字符，则会匹配成功
            Pattern ivPattern = Pattern.compile("[^A-Za-z0-9]");
            Matcher ivMatcher = ivPattern.matcher(ivParameter);
            if (ivMatcher.find()) {
                //说明有特殊字符
                logger.error("ivParameter含有特殊字符");
                return "ivParameter含有特殊字符";
            }
            if (content == null || content.isEmpty()) {
                logger.error("加密内容为空");
                return "";
            }
            SecretKeySpec secretKeySpec = getSecretKeySpec(secretKey);
            IvParameterSpec ivParameterSpec = new IvParameterSpec(ivParameter.getBytes(StandardCharsets.UTF_8));
            Cipher cipher = Cipher.getInstance(Algorithm);
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
            byte[] encryptedBytes = cipher.doFinal(content.getBytes(StandardCharsets.UTF_8));
            return Base64.getEncoder().encodeToString(encryptedBytes);
        } catch (Exception e) {
            String message = e.getMessage();
            logger.error(e.getMessage());
            return message;
        }

    }

    /**
     * @param content     content
     * @param secretKey   secretKey
     * @param ivParameter ivParameter
     * @return String
     */
    public static String decrypt(String secretKey, String ivParameter, String content) {
        try {
            //检查非空
            if (secretKey == null || secretKey.isEmpty()) {
                logger.error("secretKey为空");
                return "secretKey为空";
            }
            //检查长度
            if (secretKey.length() != 32) {
                logger.error("secretKey长度不等于32");
                return "secretKey长度不等于32";
            }
            //正则表达式标识匹配字符串中的非字母和非数字的的字符，如果字符中含有特殊字符，则会匹配成功
            Pattern pattern = Pattern.compile("[^A-Za-z0-9]");
            Matcher matcher = pattern.matcher(secretKey);
            if (matcher.find()) {
                //说明有特殊字符
                logger.error("secretKey含有特殊字符");
                return "secretKey含有特殊字符";
            }
            //***************检查非空
            if (ivParameter == null || ivParameter.isEmpty()) {
                logger.error("ivParameter为空");
                return "ivParameter为空";
            }
            //检查长度
            if (ivParameter.length() != 16) {
                logger.error("ivParameter长度不等于16");
                return "ivParameter长度不等于16";
            }
            //正则表达式标识匹配字符串中的非字母和非数字的的字符，如果字符中含有特殊字符，则会匹配成功
            Pattern ivPattern = Pattern.compile("[^A-Za-z0-9]");
            Matcher ivMatcher = ivPattern.matcher(ivParameter);
            if (ivMatcher.find()) {
                //说明有特殊字符
                logger.error("ivParameter含有特殊字符");
                return "ivParameter含有特殊字符";
            }
            if (content == null || content.isEmpty()) {
                logger.error("解密内容为空");
                return "";
            }
            byte[] encryptedBytes = Base64.getDecoder().decode(content);
            SecretKeySpec secretKeySpec = getSecretKeySpec(secretKey);
            IvParameterSpec ivParameterSpec = new IvParameterSpec(ivParameter.getBytes(StandardCharsets.UTF_8));
            Cipher cipher = Cipher.getInstance(Algorithm);
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
            byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
            return new String(decryptedBytes, StandardCharsets.UTF_8);
        } catch (Exception e) {
            String message = e.getMessage();
            logger.error(e.getMessage());
            return message;
        }
    }

    private static SecretKeySpec getSecretKeySpec(String password) throws Exception {
        return new SecretKeySpec(password.getBytes(), "AES");
    }

}
